package com.wctj.api.business.cmb.service.handle;

import com.wctj.api.base.Result;
import com.wctj.api.base.entity.DdwxPaymentRecord;
import com.wctj.api.base.enums.*;
import com.wctj.api.base.utils.*;
import com.wctj.api.base.exception.CustomException;
import com.wctj.api.business.cmb.enums.CmbPayStatusEnums;
import com.wctj.api.business.common.component.AsyncTransactionalEvent;
import com.wctj.api.business.common.dto.DdwxPaymentCfgInfoDTO;
import com.wctj.api.business.common.dto.DdwxPaymentMessageInfoDTO;
import com.wctj.api.business.common.service.DdwxPaymentCfgInfoService;
import com.wctj.api.business.common.service.DdwxPaymentRecordService;
import com.wctj.api.business.common.service.handler.CmbAbstractEventTypeResponse;
import com.wctj.api.infra.common.bean.NoticeParams;
import com.wctj.api.infra.common.bean.NoticeRequest;
import com.wctj.api.infra.common.util.IOUtils;
import com.wctj.api.infra.web.support.HttpRequestNoticeParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 招行-rechange event type 支付回调响应模式处理
 */
@Slf4j
@Service
public class CmbYQN01010EventTypeResponse extends CmbAbstractEventTypeResponse {
    @Resource
    private DdwxPaymentRecordService ddwxPaymentRecordService;
    @Resource
    private DdwxPaymentCfgInfoService ddwxPaymentCfgInfoService;
    @Value("${paysystem.cmb.phpCallbackBizCode:60000}")
    private String phpCallbackBizCode;
    @Resource
    private ApplicationContext applicationContext;

    @Transactional(rollbackFor = {Exception.class})
    public String savePaymentRecord(NoticeParams noticeParams) {
        // 支付交易Id
        String payOrderNum = OrderIdUtils.getOrderId();
        DdwxPaymentRecord paymentRecord = new DdwxPaymentRecord();
        paymentRecord.setBizCode(phpCallbackBizCode);//cmb
        paymentRecord.setPlatform(PayChannelEnums.ADAPAY_CMBPAY.getType().name());
        paymentRecord.setBizOrderNum(payOrderNum);
        paymentRecord.setPayChannel(PayChannelEnums.ADAPAY_CMBPAY.getCode());
        paymentRecord.setPayOrderNum(payOrderNum);
        //取一个唯一标识
        /**
         * notdat={"msgdat":{"yurref":"202409241110002","refnbr":"c0446ZJ000G9YQZ"}}
         */
        String yurref = "";
        BigDecimal bigDecimal = new BigDecimal("0.00");

        //JSONObject notdatObj = JSONObject.parseObject(noticeParams.getBodyStr()).getJSONObject("notdat");
        //JSONObject notdatObj = (JSONObject) JacksonUtil.parse(noticeParams.getBodyStr(),Map.class).get("notdat");
        JSONObject notdatObj =  JsonUtils.convertValue(noticeParams.getBody().get("notdat"), JSONObject.class);
        if (notdatObj != null) {
            JSONObject msgdatOBj = notdatObj.optJSONObject("msgdat");
            if (msgdatOBj != null) {
                yurref = msgdatOBj.optString("yurref");
                if (StringUtils.isBlank(yurref)){ //线下充值 yurref 存在空值
                    yurref = msgdatOBj.optString("refnbr");
                }
                if (StringUtils.isNotBlank(msgdatOBj.optString("c_trsamt"))){
                    bigDecimal = new BigDecimal(msgdatOBj.optString("c_trsamt"));
                }
            }
        }
        paymentRecord.setMoney(bigDecimal);
        paymentRecord.setPayNum(yurref);
        // 处理中
        String systemPlatform =(String) noticeParams.getAttrs().get("systemPlatform");
        DdwxPaymentCfgInfoDTO cfgInfo = ddwxPaymentCfgInfoService.queryInfoByBizCodeAndPlatform(phpCallbackBizCode,systemPlatform);
        paymentRecord.setStatus(CmbPayStatusEnums.succeeded.getCode()); //后续增加对应枚举  PayStatusEnums
//        paymentRecord.setNotifyUrl(Objects.isNull(cfgInfo) ? "" : cfgInfo.getNotifyUrl());
//        paymentRecord.setRequestBody("");
//        paymentRecord.setResponseMsg(JsonUtils.toJson(noticeParams.getBody()));
        //paymentRecord.setNotifyUrl("https://a.zgzgmall.cn/notify.php");
        //paymentRecord.setRequestBody(JsonUtils.toJson(noticeParams.getBody()));
        //paymentRecord.setResponseMsg("");
        paymentRecord.setVersion(0);
        paymentRecord.setPayTime(TimeUtils.getNow());
        paymentRecord.setPayType(PayBusinessTypeEnums.RECHANGE.name());
        // save db
        ddwxPaymentRecordService.save(paymentRecord);

        // message db
        DdwxPaymentMessageInfoDTO msgInfo = new DdwxPaymentMessageInfoDTO();
        msgInfo.setBizCode(paymentRecord.getBizCode());
        //TO-DO 事件类型，需要整理成招商的事件类型
        msgInfo.setEventType(getEventType());
        msgInfo.setPayOrderNum(payOrderNum);
        msgInfo.setPushStatus(CmbPayStatusEnums.pending.getCode());
        msgInfo.setStatus(paymentRecord.getStatus());
        msgInfo.setNotifyUrl(Objects.isNull(cfgInfo) ? "" : cfgInfo.getNotifyUrl());
        msgInfo.setRequestBody("");
        msgInfo.setResponseMsg("");
        msgInfo.setPlatform(PayPlatformEnums.CMB_PAY.name());
        //message save
        saveMessage(msgInfo);
        return payOrderNum;
    }

    @Override
    public NoticeParams getNoticeParams(NoticeRequest request) {
        NoticeParams noticeParams = new NoticeParams();
        try (InputStream is = request.getInputStream()) {
            String body = IOUtils.toString(is);
            noticeParams.setBodyStr(body);
            //noticeParams.setBody(JSON.parseObject(body));
            noticeParams.setBody(JacksonUtil.parse(body,Map.class));
        } catch (IOException e) {
            throw new CustomException(ApiCode.PAY_CALLBACK_PARAM_ERROR, e);
        }
        Map<String, List<String>> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
        noticeParams.setHeaders(headers);
        return noticeParams;
    }

    @Override
    public String businessHandle(HttpRequestNoticeParams requestNoticeParam) {
        return "";
    }

    @Override
    public String businessHandle(NoticeParams noticeParams) {
        // 支付信息存储            //直接把消息本地存储一份  转给业务方
        String payOrderNum = savePaymentRecord(noticeParams);
        // 异常事件处理
        applicationContext.publishEvent(new AsyncTransactionalEvent(this, "CmbYQN01010EventTypeResponse:" + Thread.currentThread().getId(),
                () -> {
                    try {
                        payBack(noticeParams, payOrderNum);
                    } catch (Exception e) {
                        log.error("支付分发失败", e);
                    }
                }));

        return noticeParams.getBodyStr();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payBack(NoticeParams noticeParams, String payOrderNum) {
        log.info("cmb payBack param：{}", noticeParams.getBodyStr());
        // 推送时间
        LocalDateTime pushTime = TimeUtils.getNow();
        int pushStatus = 0;
        // 发送通知推送
        //Result result = new Result(ApiCode.CMB,JSONObject.parseObject(noticeParams.getBodyStr()));
        Result result = new Result(ApiCode.CMB,JacksonUtil.parse(noticeParams.getBodyStr(),Map.class));
        String noticeBodyJsonStr = JsonUtils.toJson(result);
        //增加签名信息
        noticeBodyJsonStr = addRequestSignature(noticeBodyJsonStr);
        String systemPlatform =(String) noticeParams.getAttrs().get("systemPlatform");
        DdwxPaymentCfgInfoDTO cfgInfo = ddwxPaymentCfgInfoService.queryInfoByBizCodeAndPlatform(phpCallbackBizCode,systemPlatform);
        String notifyUrl = cfgInfo.getNotifyUrl();
        try {
            log.info("cmb notify parameter：{}", noticeBodyJsonStr);
            String resultMsg = HttpClientUtil.postJSON(notifyUrl, null, noticeBodyJsonStr);
            log.info("cmb notify result：{}", resultMsg);
            // 转义结果
            Result rts = JacksonUtil.parse(resultMsg, Result.class);
            if (Objects.nonNull(rts) && rts.getCode() == ApiCode.OK.getCode().intValue()) {
                pushStatus = CmbPayStatusEnums.succeeded.getCode();
            } else {
                pushStatus = CmbPayStatusEnums.failed.getCode();
            }
        } catch (Exception ex) {
            log.error("招商YQN01010支付回调异常", ex);
            pushStatus = CmbPayStatusEnums.failed.getCode();
        } finally {
            // message update
            //TO-DO (String orderNo, int status, int pushStatus, LocalDateTime pushTime, String noticeBodyJsonStr)
            updateMessage(payOrderNum,CmbPayStatusEnums.succeeded.getCode(),pushStatus,pushTime,noticeParams.getBodyStr());
        }
        log.info("cmb payBack result：{}", noticeParams.getBodyStr());
    }

    @Override
    public String getEventType() {
        return EventTypeEnums.YQN01010.getType();
    }

}
